﻿using gt.rediscache.core.Connections.ClientServer;
using gt.rediscache.core.Entry;
using StackExchange.Redis;
using System;
using System.Collections.Generic;

namespace gt.rediscache.core
{
    public interface IRedisClient : IRedisClientAsync, IDisposable
    {
        /// <summary>
        /// 缓存名称
        /// </summary>
        string AppCacheName { get; }
        /// <summary>
        /// 缓存配置
        /// </summary>
        RedisClientConfiguration Options { get; }
        /// <summary>
        /// 备 缓存客户端
        /// </summary>
        IRedisClient BackupClient { get; }

        #region Server

        /// <summary>
        /// 获取缓存客户端信息
        /// </summary>
        /// <returns></returns>
        RedisClientInfo RedisCacheInfo();
        /// <summary>
        /// 获取RedisClientServer
        /// </summary>
        /// <returns></returns>
        RedisClientServer GetClientServerByNodeName(string nodeName);
        /// <summary>
        /// 获取RedisClientServer
        /// </summary>
        /// <returns></returns>
        RedisClientServer[] GetClientServers();
        /// <summary>
        /// 获取RedisClientServer
        /// </summary>
        /// <returns></returns>
        RedisClientServer GetClientServer(string key);
        /// <summary>
        /// 获取RedisClientServer
        /// item1=clientServer item2=是否发生switch
        /// </summary>
        /// <returns></returns>
        Tuple<RedisClientServer, bool> GetSmartClientServer(string key);

        #endregion

        /// <summary>
        /// 获取分布式锁
        /// </summary>
        /// <returns></returns>
        bool LockTake(string key, string value, TimeSpan expiredTime);
        /// <summary>
        /// 获取分布式锁value
        /// </summary>
        /// <returns></returns>
        string LockQuery(string key);
        /// <summary>
        /// 释放分布式锁
        /// </summary>
        /// <returns></returns>
        bool LockRelease(string key, string value);
        /// <summary>
        /// 获取Redis信息
        /// </summary>
        /// <param name="hostAndport"></param>
        /// <returns></returns>
        RedisInfo RedisInfo(string hostAndport);
        /// <summary>
        /// 获取Redis连接信息
        /// </summary>
        /// <returns></returns>
        ConnectClientInfo[] RedisClients(string hostAndport);

        #region Key

        /// <summary>
        /// Key是否存在
        /// </summary>
        bool KeyExists(string key, CommandFlags flags = CommandFlags.None);
        /// <summary>
        /// 删除Key
        /// </summary>
        bool KeyRemove(string key, CommandFlags flags = CommandFlags.None);
        /// <summary>
        /// 批量删除key,
        //  集群模式不支持
        /// </summary>
        long KeyRemove(string[] keys, CommandFlags flags = CommandFlags.None);
        /// <summary>
        /// 设置key过期时间
        /// </summary>
        bool KeyExpired(string key, TimeSpan expiredTime, CommandFlags flags = CommandFlags.None);
        /// <summary>
        /// 查看key的过期时间
        /// </summary>
        TimeSpan? KeyTimeToLive(string key, CommandFlags flags = CommandFlags.None);

        #endregion

        #region String

        /// <summary>
        /// 设置string key-value
        /// </summary>
        bool StringSet(string key, string value, TimeSpan? expiredTime = null, When when = When.Always, CommandFlags flags = CommandFlags.None);

        //bool StringSet(string key, string value,bool writeFailover, TimeSpan? expiredTime = null, When when = When.Always, CommandFlags flags = CommandFlags.None);
        /// <summary>
        /// append string
        /// 返回 append后 string length
        /// </summary>
        long StringAppend(string key, string value, TimeSpan? expiredTime = null, CommandFlags flags = CommandFlags.None);
        /// <summary>
        /// 批量设置string key-value
        /// 集群模式不支持
        /// </summary>
        bool StringSet(KeyValuePair<string, string>[] keyValues, When when = When.Always, CommandFlags flags = CommandFlags.None);
        /// <summary>
        /// 设置string key-value,并返回旧值
        /// </summary>
        /// <returns></returns>
        string StringGetSet(string key, string value, TimeSpan? expiredTime = null, CommandFlags flags = CommandFlags.None);
        /// <summary>
        /// 获取string key-value
        /// </summary>
        string StringGet(string key, CommandFlags flags = CommandFlags.None);

        //string StringGet(string key, bool readFailover, CommandFlags flags);
        /// <summary>
        /// 原子性key-value 值增长
        /// </summary>
        long StringIncrement(string key, TimeSpan? expiredTime = null, long inc = 1, CommandFlags flags = CommandFlags.None);

        #endregion

        #region Hash

        /// <summary>
        /// 设置hash key field value
        /// true field is new
        /// false field is updated
        /// </summary>
        bool HashSet(string key, string field, string value, TimeSpan? expiredTime = null, When when = When.Always, CommandFlags flags = CommandFlags.None);
        /// <summary>
        /// 设置hash key 批量field value
        /// 注：如果values很大，请分批Set
        /// true field is new
        /// false field is updated
        /// </summary>
        void HashSet(string key, Dictionary<string, string> values, TimeSpan? expiredTime = null, CommandFlags flags = CommandFlags.None);
        /// <summary>
        /// 获取hash所有 field-value 值
        /// 注：如果hash内数据量很大，请使用 hashscan 方法
        /// </summary>
        Dictionary<string, string> HashGetAll(string key, CommandFlags flags = CommandFlags.None);
        /// <summary>
        /// 获取hash key field-value值
        /// </summary>
        string HashGet(string key, string field, CommandFlags flags = CommandFlags.None);
        /// <summary>
        /// Hash field是否存在
        /// </summary>
        bool HashExists(string key, string field, CommandFlags flags = CommandFlags.None);
        /// <summary>
        /// 删除hash key field-value值
        /// </summary>
        bool HashRemove(string key, string field, CommandFlags flags = CommandFlags.None);
        /// <summary>
        /// 批量删除hash key field-value值
        /// 注：如果fields很大，请分批删除
        /// </summary>
        long HashRemove(string key, string[] fields, CommandFlags flags = CommandFlags.None);
        /// <summary>
        /// 原子性 hash value 增长
        /// </summary>
        long HashIncrement(string key, string field, TimeSpan? expiredTime = null, long inc = 1, CommandFlags flags = CommandFlags.None);
        /// <summary>
        /// hash 遍历
        /// 适用于hash存有大量数据
        /// </summary>
        IEnumerable<HashEntry> HashScan(string key, string fieldPattern, int pageSize = 10, long cursor = 0, int pageOffset = 0, CommandFlags flags = CommandFlags.None);
        /// <summary>
        /// 获取hash所有的field
        /// 注：如果hash内数据量很大，请使用 hashscan 方法
        /// </summary>
        string[] HashFields(string key, CommandFlags flags = CommandFlags.None);
        /// <summary>
        /// 获取hash所有的value
        /// 注：如果hash内数据量很大，请使用 hashscan 方法
        /// </summary>
        string[] HashValues(string key, CommandFlags flags = CommandFlags.None);
        /// <summary>
        /// 获取hash长度
        /// </summary>
        long HashLength(string key, CommandFlags flags = CommandFlags.None);

        #endregion

        #region List

        /// <summary>
        /// index 获取value
        /// </summary>
        string ListGet(string key, int index, CommandFlags flags = CommandFlags.None);
        /// <summary>
        /// 在另一个value右边，插入list value,
        //   the length of the list after the insert operation, or -1 when the value pivot
        //   was not found.
        /// </summary>
        long ListInsertAfter(string key, string pivot, string insertValue, CommandFlags flags = CommandFlags.None);
        /// <summary>
        /// 在另一个value左边，插入list value,
        //   the length of the list after the insert operation, or -1 when the value pivot
        //   was not found.
        /// </summary>
        long ListInsertBefore(string key, string pivot, string insertValue, CommandFlags flags = CommandFlags.None);
        /// <summary>
        /// 返回左边头一个key-value并删除
        /// </summary>
        string ListLeftPop(string key, CommandFlags flags = CommandFlags.None);
        /// <summary>
        /// 从左边插入一个key-value
        /// 返回long length
        /// </summary>
        long ListLeftPush(string key, string value, When when = When.Always, CommandFlags flags = CommandFlags.None);
        /// <summary>
        /// list长度
        /// </summary>
        long ListLength(string key, CommandFlags flags = CommandFlags.None);
        /// <summary>
        /// 获取某一段list key-value
        /// 从 startIndex 到 endIndex(包括endIndex)
        /// </summary>
        string[] ListRange(string key, long startIndex, long endIndex, CommandFlags flags = CommandFlags.None);
        /// <summary>
        /// 返回右边头一个key-value并删除
        /// </summary>
        string ListRightPop(string key, CommandFlags flags = CommandFlags.None);
        /// <summary>
        /// 从右边插入一个key-value
        /// 返回long length
        /// </summary>
        long ListRightPush(string key, string value, When when = When.Always, CommandFlags flags = CommandFlags.None);
        /// <summary>
        /// 按序号插入value,序号不能超过队列长度
        /// </summary>
        void ListSetByIndex(string key, long index, string value, CommandFlags flags = CommandFlags.None);
        /// <summary>
        /// 保留队列一段数据
        /// </summary>
        void ListTrim(string key, long start, long stop, CommandFlags flags = CommandFlags.None);
        /// <summary>
        /// 移除队列中first count个数 匹配的值
        /// count > 0: 按从头到尾的顺序移除count个.
        /// count < 0: 按从尾到头的顺序移除count个.  
        /// count = 0: 移除所有匹配的值.
        /// </summary>
        long ListRemove(string key, string value, long count = 0, CommandFlags flags = CommandFlags.None);

        #endregion

        #region Set

        /// <summary>
        /// 插入一个value,若set中不存在，返回true.若存在，则忽略，返回false
        /// </summary>
        bool SetAdd(string key, string value, CommandFlags flags = CommandFlags.None);
        /// <summary>
        /// 插入多个value，返回插入的个数，不包括已经存在的value
        /// </summary>
        long SetAdd(string key, string[] values, CommandFlags flags = CommandFlags.None);
        /// <summary>
        /// 集合 交/并/差 集,返回结果集
        /// 集群模式不支持
        /// </summary>
        string[] SetCombine(SetOperation operation, string[] keys, CommandFlags flags = CommandFlags.None);
        /// <summary>
        /// 集合 交/并/差 集，返回结果集
        /// 集群模式不支持
        /// </summary>
        string[] SetCombine(SetOperation operation, string first, string second, CommandFlags flags = CommandFlags.None);
        /// <summary>
        /// 集合 交/并/差 集,并存入另一个集合中，返回结果集长度
        /// 集群模式不支持
        /// </summary>
        long SetCombineAndStore(SetOperation operation, string destination, string[] keys, CommandFlags flags = CommandFlags.None);
        /// <summary>
        /// 集合 交/并/差 集,并存入另一个集合中，返回结果集长度
        /// 集群模式不支持
        /// </summary>
        long SetCombineAndStore(SetOperation operation, string destination, string first, string second, CommandFlags flags = CommandFlags.None);
        /// <summary>
        /// 集合是否包含某成员
        /// </summary>
        bool SetContains(string key, string value, CommandFlags flags = CommandFlags.None);
        /// <summary>
        /// 集合长度
        /// </summary>
        long SetLength(string key, CommandFlags flags = CommandFlags.None);
        /// <summary>
        /// 集合所有成员
        /// </summary>
        string[] SetMembers(string key, CommandFlags flags = CommandFlags.None);
        /// <summary>
        /// 转移集合某个成员至另外一个集合，成功返回true,若value不是source一员你，返回false
        /// 集群模式不支持
        /// </summary>
        bool SetMove(string source, string destination, string value, CommandFlags flags = CommandFlags.None);
        /// <summary>
        /// 删除并随机获得一个集合成员
        /// </summary>
        string SetPop(string key, CommandFlags flags = CommandFlags.None);
        /// <summary>
        /// 返回一个随机成员
        /// </summary>
        string SetRandomMember(string key, CommandFlags flags = CommandFlags.None);
        /// <summary>
        /// 返回一定数量的集合成员
        /// </summary>
        string[] SetRandomMembers(string key, long count, CommandFlags flags = CommandFlags.None);
        /// <summary>
        /// 删除一批集合成员，返回实际删除的数量
        /// </summary>
        long SetRemove(string key, string[] values, CommandFlags flags = CommandFlags.None);
        /// <summary>
        /// 删除集合成员，成功删除返回true
        /// </summary>
        bool SetRemove(string key, string value, CommandFlags flags = CommandFlags.None);

        #endregion

        #region SortSet

        /// <summary>
        /// 新增集合数据
        /// True if the value was added, False if it already existed (the score is still updated)
        /// </summary>
        bool SortedSetAdd(string key, string member, double score, When when = When.Always, CommandFlags flags = CommandFlags.None);
        /// <summary>
        /// 集合数据score -value
        /// </summary>
        double SortedSetDecrement(string key, string member, double value, CommandFlags flags = CommandFlags.None);
        /// <summary>
        /// 集合数据score +value
        /// </summary>
        double SortedSetIncrement(string key, string member, double value, CommandFlags flags = CommandFlags.None);
        /// <summary>
        /// 集合分数段长度，默认全长，且包括起始段
        /// </summary>
        /// <returns></returns>
        long SortedSetLength(string key, double min = -1.0 / 0.0, double max = 1.0 / 0.0, Exclude exclude = Exclude.None, CommandFlags flags = CommandFlags.None);
        /// <summary>
        /// 集合Index段内的数据，默认全长，且包括起始段
        /// </summary>
        string[] SortedSetRangeByRank(string key, long start = 0, long stop = -1, Order order = Order.Ascending, CommandFlags flags = CommandFlags.None);
        /// <summary>
        /// 集合分数段内的数数据，默认全长，且包括起始段
        /// </summary>
        /// <param name="key"></param>
        string[] SortedSetRangeByScore(string key, double start = -1.0 / 0.0, double stop = 1.0 / 0.0, Exclude exclude = Exclude.None, Order order = Order.Ascending, long skip = 0, long take = -1, CommandFlags flags = CommandFlags.None);
        /// <summary>
        /// 删除集合成员
        /// </summary>
        bool SortedSetRemove(string key, string member, CommandFlags flags = CommandFlags.None);

        #endregion

        #region HyperLogLog

        /// <summary>
        /// 新增一个值，估值变化
        /// </summary>
        bool HyperLogLogAdd(string key, string value, CommandFlags flags = CommandFlags.None);
        /// <summary>
        /// 新增多个值，估值变化
        /// </summary>
        bool HyperLogLogAdd(string key, string[] values, CommandFlags flags = CommandFlags.None);
        /// <summary>
        /// 获取HyperLogLog的近似基数
        /// </summary>
        long HyperLogLogLength(string key, CommandFlags flags = CommandFlags.None);
        /// <summary>
        /// 获取多个HyperLogLog的近似基数的并集
        /// </summary>
        long HyperLogLogLength(string[] keys, CommandFlags flags = CommandFlags.None);
        /// <summary>
        /// 多个HyperLogLog合并到一个新的HyperLogLog结构中
        /// </summary>
        void HyperLogLogMerge(string destination, string[] sourceKeys, CommandFlags flags = CommandFlags.None);
        /// <summary>
        /// 多个HyperLogLog合并到一个新的HyperLogLog结构中
        /// </summary>
        void HyperLogLogMerge(string destination, string first, string second, CommandFlags flags = CommandFlags.None);

        #endregion

        #region Bitmaps

        /// <summary>
        /// 获取Bit统计数据
        /// </summary>
        long StringBitCount(string key, long start = 0, long end = -1, CommandFlags flags = CommandFlags.None);
        /// <summary>
        /// 多个Bit数据ADD/OR/XOR/NOT操作，并将结果存到一个新的Bit数据中
        /// </summary>
        long StringBitOperation(Bitwise operation, string destination, string[] keys, CommandFlags flags = CommandFlags.None);
        /// <summary>
        /// 多个Bit数据ADD/OR/XOR/NOT操作，并将结果存到一个新的Bit数据中
        /// </summary>
        long StringBitOperation(Bitwise operation, string destination, string first, string second = null, CommandFlags flags = CommandFlags.None);
        /// <summary>
        /// 获取第一个符合Bit的Position
        /// </summary>
        long StringBitPosition(string key, bool bit, long start = 0, long end = -1, CommandFlags flags = CommandFlags.None);
        /// <summary>
        /// 获取Bit Position值
        /// </summary>
        bool StringGetBit(string key, long offset, CommandFlags flags = CommandFlags.None);
        /// <summary>
        /// 设置Bit Position值
        /// </summary>
        bool StringSetBit(string key, long offset, bool bit, CommandFlags flags = CommandFlags.None);

        #endregion
    }
}
